package com.yunkeji.api.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yunkeji.api.call.mapper.ApiCallSheetInfoMapper;
import com.yunkeji.api.user.bo.DataCountBo;
import com.yunkeji.api.user.mapper.ApiAppUserMapper;
import com.yunkeji.api.user.mapper.ApiPayWithDrawMapper;
import com.yunkeji.api.user.service.AppUserAnalyseService;
import com.yunkeji.api.user.service.AppUserInfoService;
import com.yunkeji.api.user.vo.CountVo;
import com.yunkeji.api.user.vo.FriendsCount;
import com.yunkeji.api.user.vo.MsgCount;
import com.yunkeji.api.user.vo.OnlineCountVo;
import com.yunkeji.common.enums.app.EnableEnum;
import com.yunkeji.common.enums.app.PayLogTypeEnums;
import com.yunkeji.common.enums.app.SexEnum;
import com.yunkeji.common.exception.AppServiceException;
import com.yunkeji.common.helper.LoginHelper;
import com.yunkeji.dao.domain.AppUserExt;
import com.yunkeji.dao.domain.UserFocus;
import com.yunkeji.dao.domain.UserVisit;
import com.yunkeji.dao.mapper.AppUserExtMapper;
import com.yunkeji.dao.mapper.UserFocusMapper;
import com.yunkeji.dao.mapper.UserVisitMapper;

import lombok.AllArgsConstructor;

import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class AppUserAnalyseServiceImpl implements AppUserAnalyseService {
    private final ApiPayWithDrawMapper apiPayWithDrawMapper;
    private final ApiAppUserMapper appUserMapper;
    private final AppUserExtMapper appUserExtMapper;
    private final UserFocusMapper userFocusMapper;
    private final ApiCallSheetInfoMapper apiCallSheetInfoMapper;
    private final AppUserInfoService appUserInfoService;
    private final UserVisitMapper userVisitMapper;
    private final ApiAppUserMapper apiAppUserMapper;

    /**
     * 消息中心统计
     *
     * @author 老张
     */
    @Override
    public MsgCount msgCount() {
        MsgCount count = new MsgCount();
        SexEnum sex = appUserInfoService.getOppositeSex(LoginHelper.getLoginUser());
        Integer onlineNum = appUserMapper.countOnline(sex.getCode());
        count.setOnlineCount(onlineNum);
        UserVisit userVisit =
                userVisitMapper.selectOne(
                        Wrappers.lambdaQuery(UserVisit.class)
                                .eq(UserVisit::getToUserId, LoginHelper.getUserId())
                                .orderByDesc(UserVisit::getUpdateTime)
                                .last(" limit 1"));

        // 灵魂邂逅的人数
        Integer countRandomMatch =
                apiAppUserMapper.countRandomMatch(LoginHelper.getPlatformId(), sex.getCode());
        count.setSoulMatchNum(countRandomMatch);
        if (userVisit != null) {
            MsgCount.Visit visit = BeanUtil.toBean(userVisit, MsgCount.Visit.class);
            AppUserExt appUserExt = appUserExtMapper.selectById(userVisit.getFromUserId());
            visit.setAge(appUserExt.getAge());
            count.setVisit(visit);
            return count;
        } else {
            return count;
        }
    }

    /**
     * 对立性别的在线人数
     *
     * @author 老张
     */
    @Override
    public OnlineCountVo onlineCount() {
        SexEnum sex = appUserInfoService.getOppositeSex(LoginHelper.getLoginUser());
        Integer onlineNum = appUserMapper.countOnline(sex.getCode());
        return OnlineCountVo.builder().onlineCount(onlineNum).build();
    }

    /**
     * 统计
     *
     * @return
     */
    @Override
    public CountVo todayCount(DataCountBo bo) {
        Integer type = bo.getType();
        Date date = bo.getDate();
        CountVo build = CountVo.builder().build();
        DateTime dateTime = DateUtil.offsetDay(date, -1);
        String currentDate = DateUtil.format(date, DatePattern.PURE_DATE_PATTERN);
        String beforeDate = DateUtil.format(dateTime, DatePattern.PURE_DATE_PATTERN);
        switch (type) {
            case 1:
                // 盈利
                build.setChooseData(countEarn(currentDate));
                build.setBeforeChooseData(countEarn(beforeDate));
                return build;
            case 2:
                // 支付
                build.setChooseData(countPay(currentDate));
                build.setBeforeChooseData(countPay(beforeDate));
                return build;
            case 3:
                // 提现
                build.setChooseData(countWithDraw(currentDate));
                build.setBeforeChooseData(countWithDraw(beforeDate));
                return build;
            default:
                return build;
        }
    }

    @Override
    public FriendsCount friendsCount() {
        FriendsCount friendsCount = new FriendsCount();
        // 我关注的
        friendsCount.setFansNum(
                userFocusMapper.selectCount(
                        Wrappers.lambdaQuery(UserFocus.class)
                                .eq(UserFocus::getDelFlag, EnableEnum.NO.getCode())
                                .eq(UserFocus::getFocusUserId, LoginHelper.getUserId())));

        // 关注我的
        friendsCount.setFocusNum(
                userFocusMapper.selectCount(
                        Wrappers.lambdaQuery(UserFocus.class)
                                .eq(UserFocus::getDelFlag, EnableEnum.NO.getCode())
                                .eq(UserFocus::getFansUserId, LoginHelper.getUserId())));
        return friendsCount;
    }

    /**
     * 统计提现
     *
     * @param date
     * @return
     */
    private CountVo.DetailData countWithDraw(String date) {
        CountVo.DetailData detailData = new CountVo.DetailData();
        CountVo.CountWithDrawData data =
                apiPayWithDrawMapper.countWithDraw(LoginHelper.getUserId(), date);
        if (data != null) {
            detailData.setWithDrawNum(data.getWithDrawNum());
        }
        return detailData;
    }

    /**
     * 统计支出
     *
     * @param date
     * @return
     */
    private CountVo.DetailData countPay(String date) {
        CountVo.DetailData detailData = new CountVo.DetailData();
        List<CountVo.CountPayLogData> countData =
                appUserMapper.countPay(
                        LoginHelper.getUserId(), date, PayLogTypeEnums.getCountPayStr());
        Map<Integer, BigDecimal> collect =
                countData.stream()
                        .collect(
                                Collectors.toMap(
                                        CountVo.CountPayLogData::getLogType,
                                        CountVo.CountPayLogData::getChangeNum));
        countData.forEach(
                item -> {
                    PayLogTypeEnums byCode = PayLogTypeEnums.getByCode(item.getLogType());
                    switch (byCode) {
                        case 消费_拨打视频:
                            // 有退费
                            BigDecimal callVideo =
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO);
                            BigDecimal callback =
                                    collect.getOrDefault(
                                            PayLogTypeEnums.收益_通话预付费返还.getCode(), BigDecimal.ZERO);
                            detailData.setPayVideo(callVideo.subtract(callback));
                            break;
                        case 消费_赠送礼物:
                            detailData.setPayGift(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 消费_文字聊天消费:
                            detailData.setPayChat(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                    }
                });
        // 统计话单
        return countCall(detailData, date);
    }

    /**
     * 统计盈利
     *
     * @param date
     * @return
     */
    private CountVo.DetailData countEarn(String date) {
        CountVo.DetailData detailData = new CountVo.DetailData();
        List<CountVo.CountPayLogData> countData =
                appUserMapper.countEarn(
                        LoginHelper.getUserId(), date, PayLogTypeEnums.getCountEarnStr());
        Map<Integer, BigDecimal> collect =
                countData.stream()
                        .collect(
                                Collectors.toMap(
                                        CountVo.CountPayLogData::getLogType,
                                        CountVo.CountPayLogData::getChangeNum));
        countData.forEach(
                item -> {
                    PayLogTypeEnums byCode = PayLogTypeEnums.getByCode(item.getLogType());
                    switch (byCode) {
                        case 收益_接受视频:
                            detailData.setEarnVideo(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 收益_接收礼物:
                            detailData.setEarnGift(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 收益_文字聊天收益:
                            detailData.setEarnChat(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 收益_活动奖励:
                            detailData.setEarnActive(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 收益_任务奖励:
                            detailData.setEarnTask(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 收益_邀请视频收益:
                            detailData.setEarnInvitedVideo(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 收益_邀请充值收益:
                            detailData.setEarnInvitedRecharge(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        case 收益_邀请礼物收益:
                            detailData.setEarnInvitedGift(
                                    collect.getOrDefault(byCode.getCode(), BigDecimal.ZERO));
                            break;
                        default:
                            throw AppServiceException.paramException("统计盈利参数异常");
                    }
                });
        return countCall(detailData, date);
    }

    private CountVo.DetailData countCall(CountVo.DetailData countVo, String date) {
        CountVo.CountCallData callData =
                apiCallSheetInfoMapper.countToday(LoginHelper.getUserId(), date);
        if (callData != null) {
            if (callData.getDuration() != null) {
                BigDecimal divide =
                        BigDecimal.valueOf(callData.getDuration())
                                .divide(BigDecimal.valueOf(60), 0, RoundingMode.UP);
                countVo.setCallTime(divide.intValue());
            }
            int callSum = callData.getCallSum() == null ? 0 : callData.getCallSum();
            int answerSum = callData.getAnswerSum() == null ? 0 : callData.getAnswerSum();
            countVo.setCallPersonNum(callSum + answerSum);
        }
        return countVo;
    }
}
